/*  ----------------------------------------------------------------------------
 *  Arello Mobile
 *  Fast 3d Engine
 *  ----------------------------------------------------------------------------
 * Except where otherwise noted, this work is licensed under
 * http://creativecommons.org/licenses/by/3.0
 */
#pragma once

#include <vector>
#include <string>
#include <resource/Resource.h>
#include "XMInstrument.h"
#include "Pattern.h"
#include "Format.h"

class XMChannel;

//#define SAMPLE_WRITER
#define EXTERN_SAMPLES

#ifdef SAMPLE_WRITER
extern void * xm_data_for_sample_writer;
#endif

class XMPlayer
{
//	AutoPtr< Resource > resource;

	std::vector< XMChannel * > channels;

	std::string module_name;
	std::string tracker_name;
	unsigned short tracker_version;

	unsigned short song_length;
	unsigned short restart_position;

	bool use_linear_table; //otherwise - amiga table

	unsigned short original_speed;
	unsigned short original_bpm;

	std::vector< int > pattern_order;
	std::vector< XMPattern > patterns;

	std::vector< XMInstrument * > instruments;

	int global_volume;
	unsigned short current_speed;
	unsigned short current_bpm;

	int real_pattern;
	int current_pattern_index;
	int next_pattern_index;

	int pattern_delay;
	int next_read_note_tick;
	int buffer_size_before_next_update;
	int current_row;

	Format format;
	bool interpolate;

	bool valid;

	void start_update();
	bool advance_row();

public:
	XMPlayer(resource::Resource *resource, const Format & format, bool interpolate );
	~XMPlayer();

	void reset();	//reset all positions. use this method to play xm in loop
	int read( void * where, int samples_count ); // ADDS music, so do not forget to zero memory before calling this


	const Format & get_format()const
	{
		return format;
	}
	bool is_valid()const
	{
		return valid;
	}
	void position_jump( int pattern )
	{
		next_pattern_index = pattern;
		current_row = 0xFFFFF;
	}
	void pattern_break_to_row( int row )
	{
		++current_pattern_index;
		++next_pattern_index;
		real_pattern = pattern_order[ current_pattern_index ];
		current_row = row;
	}
	void set_row( int row )
	{
		current_row = row;
	}
	void set_pattern_delay( int param )
	{
		pattern_delay = param;
	}
	void set_global_volume( int param )
	{
		global_volume = param * 2;
	}
	void set_bpm( int param )
	{
		current_bpm = param;
	}
	void set_speed( int param )
	{
		current_speed = param;
	}
	bool is_linear_table()const
	{
		return use_linear_table;
	}
	const XMInstrument * get_instrument( unsigned number )const
	{
		if( number >= instruments.size() )
			return 0;

		return instruments[number];
	}
	const Note & get_note( int channel_num )const
	{
		return patterns[ real_pattern ].get_note( current_row, channel_num );
	}
	int get_global_volume()const
	{
		return global_volume;
	}
};

